package com.cbs.android.widget.tipview;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewParent;
import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

/**
 * Created by broche on 7/4/16.
 */
public class TipView extends FrameLayout implements Observer {
    private static final String TAG = TipView.class.getName();
    /**
     * 动画间隔
     */
    private static final int ANIM_DELAYED_MILLIONS = 3 * 1000;
    /**
     * 动画持续时长
     */
    private static final int ANIM_DURATION = 1 * 1000;
    private Adapter adapter = null;
    private List<ViewHolder> viewHolders = new ArrayList<>();
    private RefreshHandler refreshHandler = new RefreshHandler();
    private Animation animIn;
    private Animation animOut;
    private int index = 0;
    private com.cbs.android.widget.tipview.OnClickListener onClickListener = null;

    public TipView(Context context) {
        super(context);
        initAnimation();
    }

    public TipView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAnimation();
    }

    public TipView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAnimation();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        ViewParent cview = this;
        while (cview.getParent() != null) {
            if (RecyclerView.class.isAssignableFrom(cview.getParent().getClass())) {
                RecyclerView parentView = (RecyclerView) cview.getParent();
                parentView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
                    @Override
                    public void onChildViewAttachedToWindow(View view) {
                        if (view == TipView.this) {
                            startAnimate();
                        }
                    }

                    @Override
                    public void onChildViewDetachedFromWindow(View view) {
                        if (view == TipView.this) {
                            stopAnimate();
                        }
                    }
                });
            }
            cview = cview.getParent();
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public TipView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initAnimation();
    }

    public void setAdapter(Adapter adapter) {
        this.adapter = adapter;
        adapter.addObserver(this);
        refreshHandler.sendEmptyMessageDelayed(0, 100);
    }

    @Override
    public void update(Observable observable, Object data) {
        refreshHandler.sendEmptyMessage(0);
    }

    public void stopAnimate() {
        if (viewHolders.size() > 0) {
            int curIndex = index;
            int nextIndex = (index + 1) % viewHolders.size();
            for (int i = 0; i < viewHolders.size(); i++) {
                if (i == curIndex || i == nextIndex) {
                    viewHolders.get(i).itemView.setVisibility(View.VISIBLE);
                } else {
                    viewHolders.get(i).itemView.setVisibility(View.INVISIBLE);
                }
                viewHolders.get(i).itemView.clearAnimation();
            }
        }
    }

    public void startAnimate() {
        updateTipAndPlayAnimation();
    }

    @Override
    public void setOnClickListener(OnClickListener listener) {
        throw new RuntimeException("this method is forbitted");
    }

    public void setOnClickListener(com.cbs.android.widget.tipview.OnClickListener listener) {
        this.onClickListener = listener;
        super.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (onClickListener != null) {
                    onClickListener.onClick(v, getIndex());
                }
            }
        });
    }

    public int getIndex() {
        if (adapter == null) {
            return 0;
        } else if (adapter.getItemCount() <= 0) {
            return 0;
        }
        int preIndex = index - 1;
        if (preIndex < 0) {
            preIndex += adapter.getItemCount();
        }
        return preIndex;
    }

    private void reload() {
        if (adapter == null) {
            return;
        } else if (adapter.getItemCount() <= 0) {
            return;
        }
        for (int i = 0; i < viewHolders.size(); i++) {
            viewHolders.get(i).itemView.clearAnimation();
        }
        viewHolders.clear();
        removeAllViews();
        for (int i = 0; i < adapter.getItemCount(); i++) {
            int viewType = adapter.getItemViewType(i);
            ViewHolder viewHolder = adapter.onCreateViewHolder(this, viewType);
            adapter.onBindViewHolder(viewHolder, i);
            viewHolders.add(viewHolder);
            addView(viewHolder.itemView);
        }

        index = 0;
        updateTipAndPlayAnimation();
    }

    private void initAnimation() {
        animIn = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0,
                Animation.RELATIVE_TO_SELF, 1, Animation.RELATIVE_TO_SELF, 0);
        animIn.setDuration(ANIM_DURATION);
        animIn.setStartOffset(ANIM_DELAYED_MILLIONS);
        animIn.setInterpolator(new DecelerateInterpolator());

        animOut = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0,
                Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, -1);
        animOut.setDuration(ANIM_DURATION);
        animOut.setStartOffset(ANIM_DELAYED_MILLIONS);
        animOut.setInterpolator(new DecelerateInterpolator());

        animIn.setAnimationListener(new Animation.AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                updateTipAndPlayAnimation();
            }
        });
    }

    private void updateTipAndPlayAnimation() {
        if (viewHolders.size() > 0) {
            int curIndex = index;
            int nextIndex = (index + 1) % viewHolders.size();
            for (int i = 0; i < viewHolders.size(); i++) {
                if (i == curIndex || i == nextIndex) {
                    viewHolders.get(i).itemView.setVisibility(View.VISIBLE);
                } else {
                    viewHolders.get(i).itemView.setVisibility(View.INVISIBLE);
                }
                viewHolders.get(i).itemView.clearAnimation();
            }
            bringChildToFront(viewHolders.get(nextIndex).itemView);
            if (curIndex != nextIndex) {
                viewHolders.get(curIndex).itemView.startAnimation(animOut);
                viewHolders.get(nextIndex).itemView.startAnimation(animIn);
            }

            index = nextIndex;
        }
    }

    private class RefreshHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            reload();
        }
    }
}
